local snow     = require("meet_your_mods.mhr").snow
local status   = require("meet_your_mods.status")
local shortcut = require("meet_your_mods.shortcut")
local routine  = require("meet_your_mods.routine_framework")
local ui       = require("meet_your_mods.ui")

--护石稀有等级
snow.data.DataDef.PlTalismanId:fetch_enum("none", "PlTalisman_None")
snow.data.DataDef.PlTalismanId:fetch_enum("r01", "PlTalisman_000")
snow.data.DataDef.PlTalismanId:fetch_enum("r02", "PlTalisman_001")
snow.data.DataDef.PlTalismanId:fetch_enum("r03", "PlTalisman_002")
snow.data.DataDef.PlTalismanId:fetch_enum("r04", "PlTalisman_003")
snow.data.DataDef.PlTalismanId:fetch_enum("r05", "PlTalisman_004")
snow.data.DataDef.PlTalismanId:fetch_enum("r06", "PlTalisman_005")
snow.data.DataDef.PlTalismanId:fetch_enum("r07", "PlTalisman_006")
snow.data.DataDef.PlTalismanId:fetch_enum("r08", "PlTalisman_011")
snow.data.DataDef.PlTalismanId:fetch_enum("r09", "PlTalisman_012")
snow.data.DataDef.PlTalismanId:fetch_enum("r10", "PlTalisman_013")
snow.data.DataDef.PlTalismanId:fetch_enum("e08", "PlTalisman_015")
snow.data.DataDef.PlTalismanId:fetch_enum("e09", "PlTalisman_016")
snow.data.DataDef.PlTalismanId:fetch_enum("e10", "PlTalisman_017")

--炼金模式
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("suikyou", "Alchemy1")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("yougen", "Alchemy2")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("gekkou", "Alchemy3")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("yuugen", "Alchemy4")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("rinne", "Alchemy5")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("shinki", "AlchemyShinki")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("tensei", "AlchemyTensei")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("kyokkou", "AlchemyKyokkou")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("haki", "AlchemyHaki")
snow.data.AlchemyPatturnData.PatturnTypes:fetch_enum("enkan", "AlchemyEnkan")

--技能级别
snow.data.AlchemyPlSkillTableData.GradeTypes:fetch_enum("none", "Max")

local talisman = {
    config    = nil,
    ui        = {
        content = {},
        rare    = {
            name = {
                [snow.data.DataDef.PlTalismanId.r01] = "R1",
                [snow.data.DataDef.PlTalismanId.r02] = "R2",
                [snow.data.DataDef.PlTalismanId.r03] = "R3",
                [snow.data.DataDef.PlTalismanId.r04] = "R4",
                [snow.data.DataDef.PlTalismanId.r05] = "R5",
                [snow.data.DataDef.PlTalismanId.r06] = "R6",
                [snow.data.DataDef.PlTalismanId.r07] = "R7",
                [snow.data.DataDef.PlTalismanId.r08] = "R8",
                [snow.data.DataDef.PlTalismanId.r09] = "R9",
                [snow.data.DataDef.PlTalismanId.r10] = "R10",
                [snow.data.DataDef.PlTalismanId.e08] = "R8+",
                [snow.data.DataDef.PlTalismanId.e09] = "R9+",
                [snow.data.DataDef.PlTalismanId.e10] = "R10+",
            },
            text = {
                "R7", "R10", "R10+"
            },
            value = {
                snow.data.DataDef.PlTalismanId.r07,
                snow.data.DataDef.PlTalismanId.r10,
                snow.data.DataDef.PlTalismanId.e10,
            }
        },
    },
    talismans = nil,
    talisman  = nil,
    pages     = 0,
    page_size = 20,
    page      = 1,
}

function talisman:load_config()
    if self.config then
        return
    end
    self.config = {}

    --读取炼金配置
    local alchemy = self:load_alchemy_config()
    for _, alchemy in pairs(alchemy) do
        --读取技能和插槽配置
        self.config[alchemy.rare] = {
            skill = self:load_skill_config(alchemy),
            slot  = self:load_slot_config(alchemy),
        }
    end

    --生成UI
    for category, alchemy in pairs(self.config) do
        self.ui.content[category] = {
            skill = self:make_skill_ui(alchemy),
            slot  = self:make_slot_ui(alchemy),
        }
    end
end

--读取炼金配置
function talisman:load_alchemy_config()
    --读取三类炼金的配置
    local alchemy = json.load_file("meet_your_mods.talisman")
    if not alchemy then
        error("配置文件\"meet_your_mods.talisman\"无效")
    end

    --转化为游戏内部数值
    for _, config in pairs(alchemy) do
        config.rare = load("return " .. config.rare, nil, "t", { snow = snow, })()
        for index, pattern in pairs(config.pattern) do
            config.pattern[index] = load("return " .. pattern, nil, "t", { snow = snow, })()
        end
    end

    return alchemy
end

--读取护石合法技能配置
function talisman:load_skill_config(alchemy)
    if not alchemy then
        return {}
    end
    --读取支持的模式
    local patterns = {}
    for _, pattern in pairs(alchemy.pattern) do
        patterns[pattern] = true
    end

    --读取可选的技能
    local skills = {}
    for _, skill in pairs(snow.data.FacilityDataManager:get_singleton():getAlchemy():get_Function()._SkillTableUserData._Param) do
        if not patterns[skill._Patturn] then
            goto next_skill
        end

        --读取技能ID、级别和本地化名称
        local config = skills[skill._SkillId]
        if not config then
            config = {
                id    = skill._SkillId,
                name  = shortcut:get_equipment_skill_name(skill._SkillId),
                grade = skill._Grade,
                level = {
                    { min = 0, max = 0, }, --位于第一个技能槽时可选的最小、最大等级
                    { min = 0, max = 0, }, --位于第二个技能槽时可选的最小、最大等级
                },
            }
        end

        --读取技能可选等级
        for position = 1, 2 do
            local min, max = self:load_skill_level(skill["_Skill" .. position .. "RateList"])
            if 0 == min and 0 == max then
                goto next_position
            end

            if 0 == config.level[position].min then
                config.level[position].min = min
            else
                config.level[position].min = math.min(config.level[position].min, min)
            end

            if 0 == config.level[position].max then
                config.level[position].max = max
            else
                config.level[position].max = math.max(config.level[position].max, max)
            end
            ::next_position::
        end

        if config.level[1].min + config.level[1].max + config.level[2].min + config.level[2].max ~= 0 then
            skills[config.id] = config
        end
        ::next_skill::
    end

    return skills
end

--读取技能可选的最小和最大等级
function talisman:load_skill_level(config)
    local min = 0
    for level = 1, #config, 1 do
        if config[level] ~= 0 then
            min = level
            break
        end
    end

    local max = 0
    for level = #config, 1, -1 do
        if config[level] ~= 0 then
            max = level
            break
        end
    end

    return min, max
end

--读取护石合法插槽配置
function talisman:load_slot_config(alchemy)
    local functor = {
        ["normal"]  = self.load_normal_slot_config,
        ["mystery"] = self.load_mystery_slot_config,
    }

    return functor[alchemy.type](self, alchemy)
end

--读取常规炼金的合法插槽配置
function talisman:load_normal_slot_config(alchemy)
    --整个各个技能级别组合下插槽的生成概率
    local rate = self:load_slot_rate(alchemy)

    --根据概率生成插槽组合
    local slots = {}
    for grade_pos1, slot_rate in pairs(rate) do
        for grade_pos2, slot_rate in pairs(slot_rate) do
            if not slots[grade_pos1] then
                slots[grade_pos1] = {}
            end
            slots[grade_pos1][grade_pos2] = self:make_slot_config(self:load_max_slot(slot_rate))
        end
    end

    return slots
end

--读取给定炼金模式下每个插槽的生成概率
function talisman:load_slot_rate(alchemy)
    local rate = {}

    for slot_index, slot_rate_table in pairs(snow.data.FacilityDataManager:get_singleton():getAlchemy():get_Function()._LotFunc._SlotNumTableUserData._Param) do
        for _, slot_rate_table in pairs(slot_rate_table._SlotParam) do
            if snow.data.alchemy.SlotNumTableUserData.GradeTypesForUserData.None == slot_rate_table._Skill1Grade then
                goto next_table
            end

            --生成技能级别组合表
            if not rate[slot_rate_table._Skill1Grade] then
                rate[slot_rate_table._Skill1Grade] = {}
            end
            if not rate[slot_rate_table._Skill1Grade][slot_rate_table._Skill2Grade] then
                rate[slot_rate_table._Skill1Grade][slot_rate_table._Skill2Grade] =
                {
                    { 0, 0, 0, 0, 0, }, { 0, 0, 0, 0, 0, }, { 0, 0, 0, 0, 0, },
                }
            end

            --读取给定炼金模式、技能级别组合下的插槽配置表
            local rate = rate[slot_rate_table._Skill1Grade][slot_rate_table._Skill2Grade]
            for _, rate_table_name in pairs(alchemy.slot) do
                local rate_table = slot_rate_table[rate_table_name]
                rate[slot_index][1] = rate[slot_index][1] + rate_table[1]
                rate[slot_index][2] = rate[slot_index][2] + rate_table[2]
                rate[slot_index][3] = rate[slot_index][3] + rate_table[3]
                rate[slot_index][4] = rate[slot_index][4] + rate_table[4]
                rate[slot_index][5] = rate[slot_index][5] + (rate_table[5] or 0)
            end
            ::next_table::
        end
    end

    return rate
end

--根据给定的每个位置的插槽生成概率计算最大可选插槽
function talisman:load_max_slot(slot_rate)
    local max_slots = { 0, 0, 0, }
    for slot_index, rate in pairs(slot_rate) do
        for index = #rate, 1, -1 do
            if rate[index] ~= 0 then
                max_slots[slot_index] = index - 1
                break
            end
        end
    end

    return max_slots
end

--根据给定的每个位置的最大插槽生成插槽组合
function talisman:make_slot_config(max_slots)
    local slots = {}

    --将四级插槽限定为"4-0-0"
    if 4 == max_slots[1] then
        table.insert(slots, { 4, 0, 0, })
        max_slots[1] = 3
    end

    for index_pos1 = max_slots[1], 0, -1 do
        for index_pos2 = math.min(max_slots[2], index_pos1), 0, -1 do
            for index_pos3 = math.min(max_slots[3], index_pos2), 0, -1 do
                table.insert(slots, { index_pos1, index_pos2, index_pos3, })
            end
        end
    end
    table.sort(slots, self.sort_slot)

    return slots
end

--读取怪异炼金的合法插槽配置
function talisman:load_mystery_slot_config(alchemy)
    local slots  = {}
    local config = {}

    for _, slot in pairs(snow.data.FacilityDataManager:get_singleton():getAlchemy():get_Function()._LotFunc._MysterySlotNumTableUserData._MysterySkillParam) do
        if slot._PickRate <= 0 then
            goto next_slot
        end
        table.insert(slots, { slot._SlotLv[1], slot._SlotLv[2], slot._SlotLv[3], })
        ::next_slot::
    end

    table.sort(slots, self.sort_slot)

    --所有技能级别组合共用一套插槽配置
    for _, pos1 in pairs({
        snow.data.AlchemyPlSkillTableData.GradeTypes.S,
        snow.data.AlchemyPlSkillTableData.GradeTypes.A,
        snow.data.AlchemyPlSkillTableData.GradeTypes.B,
        snow.data.AlchemyPlSkillTableData.GradeTypes.C,
    }) do
        for _, pos2 in pairs({
            snow.data.AlchemyPlSkillTableData.GradeTypes.S,
            snow.data.AlchemyPlSkillTableData.GradeTypes.A,
            snow.data.AlchemyPlSkillTableData.GradeTypes.B,
            snow.data.AlchemyPlSkillTableData.GradeTypes.C,
            snow.data.AlchemyPlSkillTableData.GradeTypes.none,
        }) do
            if not config[pos1] then
                config[pos1] = {}
            end
            config[pos1][pos2] = slots
        end
    end

    return config
end

--插槽配置排序（降序）
function talisman.sort_slot(left, right)
    local left_hash  = left[1] * 100 + left[2] * 10 + left[3]
    local right_hash = right[1] * 100 + right[2] * 10 + right[3]
    return left_hash > right_hash
end

--为技能生成UI
function talisman:make_skill_ui(alchemy)
    local skill_ui = {
        text   = {
            { "------", },
            { "------", },
        },
        value  = {
            { snow.data.DataDef.PlEquipSkillId.none, },
            { snow.data.DataDef.PlEquipSkillId.none, },
        },
        enable = {
            { [snow.data.DataDef.PlEquipSkillId.none] = 1, },
            { [snow.data.DataDef.PlEquipSkillId.none] = 1, },
        },
        level  = { {}, {}, },
    }

    --按照技能ID升序排列
    local skill_sorted = {}
    for _, skill in pairs(alchemy.skill) do
        table.insert(skill_sorted, skill)
    end
    table.sort(skill_sorted, function(left, right) return left.id < right.id end)

    for _, skill in pairs(skill_sorted) do
        for position = 1, 2 do
            if 0 == skill.level[position].min + skill.level[position].max then
                goto next_position
            end

            --插入名称和ID
            table.insert(skill_ui.text[position], skill.name)
            table.insert(skill_ui.value[position], skill.id)
            skill_ui.enable[position][skill.id] = #skill_ui.value[position]

            --插入可选等级
            skill_ui.level[position][skill.id] = {
                min = skill.level[position].min,
                max = skill.level[position].max,
            }

            ::next_position::
        end
    end

    return skill_ui
end

--为插槽生成UI
function talisman:make_slot_ui(alchemy)
    local slots_ui = {}

    for grade_pos1, config in pairs(alchemy.slot) do
        for grade_pos2, config in pairs(config) do
            local slot_ui = { text = {}, value = config, }

            for _, slot in pairs(config) do
                table.insert(slot_ui.text, string.format("%d-%d-%d", slot[1], slot[2], slot[3]))
            end

            if not slots_ui[grade_pos1] then
                slots_ui[grade_pos1] = {}
            end
            slots_ui[grade_pos1][grade_pos2] = slot_ui
        end
    end

    return slots_ui
end

--读取装备箱中的护石
function talisman:load_talismans()
    if status.logical_status.none == status:current_status()
        or not self.config
    then
        self.talismans = nil
        self.talisman  = nil
        return
    end

    self.talismans = {}
    self.talisman  = nil
    for _, equipment in pairs(shortcut:get_equipment_inventory()) do
        if not equipment:isTalisman() then
            goto next_equipment
        end
        table.insert(self.talismans, self:load_talisman(equipment))
        ::next_equipment::
    end

    self.pages = math.ceil(#self.talismans / self.page_size)
    self.page  = 1
end

--读取给定护石
function talisman:load_talisman(instance, content)
    local talisman   = content or { instance = instance, uuid = ui:generate_uuid(), }
    talisman.id      = instance:get_TalismanId()
    talisman.rare    = self.ui.rare.name[talisman.id]
    talisman.name    = shortcut:get_talisman_name(talisman.id)

    local skill_list = instance:getTalismanSkillIdList()
    local level_list = instance:getTalismanSkillLvList()
    talisman.skill   = {}
    for skill_index = 1, 2 do
        table.insert(talisman.skill, {
            id      = skill_list[skill_index],
            level   = level_list[skill_index],
            id_text = skill_list[skill_index] ~= snow.data.DataDef.PlEquipSkillId.none
                and shortcut:get_equipment_skill_name(skill_list[skill_index]) or nil,
            lv_text = skill_list[skill_index] ~= snow.data.DataDef.PlEquipSkillId.none
                and "Lv." .. level_list[skill_index] or nil,
        })
    end

    talisman.slot = { value = {}, }
    for level_index, slot in pairs(instance:getTalismanDecoSlotNumList()) do
        for _ = 1, slot do
            table.insert(talisman.slot.value, level_index - 1)
        end
    end
    while #talisman.slot.value < 3 do table.insert(talisman.slot.value, 0) end
    table.sort(talisman.slot.value, function(left, right) return left > right end)
    talisman.slot.text = string.format("%d-%d-%d", talisman.slot.value[1], talisman.slot.value[2], talisman.slot.value
        [3])

    --检测装饰品
    for _, deco in pairs(instance:getDecoIdList()) do
        if deco ~= snow.equip.DecorationsId.Deco_None then
            talisman.has_deco = true
            break
        end
    end

    return talisman
end

function talisman:initialize()
    routine:hook(self)

    if status:current_status() ~= status.logical_status.none then
        self:post_before_village()
    end

    ui:cluster("inventory", "存档功能")
    ui:button("inventory", "编辑护石", self.toggle_window, self)
    ui:sameline("inventory")
    ui:button("inventory", "导出锁定护石", self.export, self)

    ui:child_window(function() return self.talismans end, function() self:toggle_window() end,
        "护石编辑", self.draw_window, self)
end

function talisman:normalize()
end

function talisman:pre_return_title(_)
    self.config    = nil
    self.pages     = 0
    self.page      = 0

    self.talismans = nil
    self.talisman  = nil
end

function talisman:post_before_village(_)
    self:load_config()
end

function talisman:toggle_window()
    if self.talismans then
        self.talismans = nil
        self.talisman  = nil
    else
        self:load_talismans()
    end
end

--导出锁定的护石
function talisman:export()
    if not self.config then
        return
    end

    local contents = ""
    for _, equipment in pairs(shortcut:get_equipment_inventory()) do
        if not equipment:isTalisman() or not equipment:get_IsLock() then
            goto next_inventory
        end

        local skills  = equipment:getTalismanSkillIdList()
        local levels  = equipment:getTalismanSkillLvList()
        local content = ""
        content       = content .. shortcut:get_equipment_skill_name(skills[1]) .. "," .. levels[1] .. ","
        content       = content .. shortcut:get_equipment_skill_name(skills[2]) .. "," .. levels[2] .. ","

        local slots   = {}
        for level_index, slot in pairs(equipment:getTalismanDecoSlotNumList()) do
            for _ = 1, slot do
                table.insert(slots, level_index - 1)
            end
        end
        while #slots < 3 do table.insert(slots, 0) end
        table.sort(slots, function(left, right) return left > right end)

        for _, slot in pairs(slots) do
            content = content .. slot .. ","
        end
        contents = contents .. string.sub(content, 1, -2) .. "\n"
        ::next_inventory::
    end

    fs.write(string.format("meet_your_mods.talisman.c%02d.txt", status:current_save_data()),
        string.sub(contents, 1, -2))
end

--绘制护石窗口
function talisman:draw_window()
    imgui.spacing()
    imgui.indent(4)

    if not self.talisman then
        self:draw_info_view()
    else
        self:draw_edit_view(self.talisman)
    end
end

--绘制护石展示视图
function talisman:draw_info_view()
    if 0 == #self.talismans then
        imgui.text("无护石")
        return
    end

    if imgui.button("＜") then
        self.page = self.page - 1 >= 1 and self.page - 1 or self.pages
    end

    imgui.same_line()
    imgui.text(string.format("%02d/%02d", self.page, self.pages))

    imgui.same_line()
    if imgui.button("＞") then
        self.page = self.page + 1 <= self.pages and self.page + 1 or 1
    end

    imgui.same_line()
    if imgui.button("刷新") then
        self.talisman = nil
        self:load_talismans()
    end

    if not imgui.begin_table(nil, 6, imgui.TableFlags.NoSavedSettings | imgui.TableFlags.RowBg) then
        return
    end
    imgui.table_setup_column("护石", imgui.ColumnFlags.WidthFixed)
    imgui.table_setup_column("稀有", imgui.ColumnFlags.WidthFixed)
    imgui.table_setup_column("技能", imgui.ColumnFlags.WidthStretch)
    imgui.table_setup_column("技能等级", imgui.ColumnFlags.WidthFixed)
    imgui.table_setup_column("插槽等级", imgui.ColumnFlags.WidthStretch)
    imgui.table_setup_column(nil, imgui.ColumnFlags.WidthFixed)
    imgui.table_headers_row()

    for index = (self.page - 1) * self.page_size + 1, math.min(#self.talismans, self.page * self.page_size) do
        local content = self.talismans[index]

        imgui.table_next_column()
        imgui.text(string.format("%03d - %s", index, content.name))

        imgui.table_next_column()
        imgui.text(content.rare)

        imgui.table_next_column()
        for _, skill in pairs(content.skill) do
            imgui.text(skill.id_text)
        end

        imgui.table_next_column()
        for _, skill in pairs(content.skill) do
            imgui.text(skill.lv_text)
        end

        imgui.table_next_column()
        imgui.text(content.slot.text)

        imgui.table_next_column()
        imgui.push_id(content.uuid)

        if content.has_deco then
            imgui.text("包含装饰品")
            imgui.text("无法修改")
        elseif imgui.button("修改") then
            self:normalize_talisman(content)
            self.talisman = content
        end
        imgui.pop_id()
    end
    imgui.end_table()
end

--规范化给定护石
function talisman:normalize_talisman(content, editor)
    if not editor then
        editor = {
            rare = {
                value = content.id,
                index = 0,
            },
            slot = {
                value = content.slot.value,
                index = 0,
                list  = nil,
            },
            skill = {
                {
                    id    = { value = content.skill[1].id, index = 0, },
                    level = { value = content.skill[1].level, min = 0, max = 0, },
                },
                {
                    id    = { value = content.skill[2].id, index = 0, },
                    level = { value = content.skill[2].level, min = 0, max = 0, },
                },
            },
        }
    end

    --获取兼容稀有度
    self:normalize_rare(editor.rare)

    --获取兼容技能
    for position, skill in pairs(editor.skill) do
        skill.id.index = self.ui.content[editor.rare.value].skill.enable[position][skill.id.value]

        if not skill.id.index then
            --移除非法技能
            skill.id    = { value = snow.data.DataDef.PlEquipSkillId.none, index = 1, }
            skill.level = nil

            --若首个技能不存在则移除所有技能
            if 1 == position then
                editor.skill[2].id    = { value = snow.data.DataDef.PlEquipSkillId.none, index = 1, }
                editor.skill[2].level = nil
            end
            goto next_skill
        end

        --获取兼容技能等级
        self:normalize_skill_level(editor, position)

        ::next_skill::
    end

    --获取兼容插槽
    self:normalize_slot(editor)

    content.editor = editor
end

--查询兼容稀有度
function talisman:normalize_rare(rare)
    --获取兼容稀有度
    for index = 1, #self.ui.rare.value do
        if rare.value <= self.ui.rare.value[index] then
            rare.value = self.ui.rare.value[index]
            rare.index = index
            return
        end
    end

    rare.value = self.ui.rare.value[#self.ui.rare.value]
    rare.index = #self.ui.rare.value
end

--查询兼容插槽
function talisman:normalize_slot(editor)
    local grade_pos1, grade_pos2 = self:get_skill_grade(editor)
    if snow.data.AlchemyPlSkillTableData.GradeTypes.none == grade_pos1 then
        editor.slot.value = nil
        editor.slot.index = 0
        editor.slot.list  = nil

        return
    end

    local list = self.ui.content[editor.rare.value].slot[grade_pos1][grade_pos2]
    if not list then
        editor.slot.list = nil
        return
    end

    if not editor.slot.value then
        editor.slot.value = list.value[1]
        editor.slot.index = 1
        editor.slot.list  = list
        return
    end

    local hash = editor.slot.value[1] * 100 + editor.slot.value[2] * 10 + editor.slot.value[3]
    for index = #list.value, 1, -1 do
        local current_slot = list.value[index]
        local current_hash = current_slot[1] * 100 + current_slot[2] * 10 + current_slot[3]

        if current_hash >= hash then
            editor.slot.value = list.value[1]
            editor.slot.index = 1
            editor.slot.list  = list

            return
        end
    end

    editor.slot.value = list.value[1]
    editor.slot.index = 1
    editor.slot.list  = list
end

--查询技能级别
function talisman:get_skill_grade(editor)
    local grade_pos1 = snow.data.AlchemyPlSkillTableData.GradeTypes.none
    if editor.skill[1].id.value ~= snow.data.DataDef.PlEquipSkillId.none then
        grade_pos1 = self.config[editor.rare.value].skill[editor.skill[1].id.value].grade
    end

    local grade_pos2 = snow.data.AlchemyPlSkillTableData.GradeTypes.none
    if editor.skill[2].id.value ~= snow.data.DataDef.PlEquipSkillId.none then
        grade_pos2 = self.config[editor.rare.value].skill[editor.skill[2].id.value].grade
    end

    return grade_pos1, grade_pos2
end

--查询技能等级
function talisman:normalize_skill_level(editor, position)
    local config = self.ui.content[editor.rare.value].skill.level[position][editor.skill[position].id.value]
    if not config then
        editor.skill[position].level = nil
        return
    end

    if not editor.skill[position].level then
        editor.skill[position].level = { value = 0, min = 0, max = 0, }
    end

    local level = editor.skill[position].level
    if level.value < config.min or level.value > config.max then
        level.value = config.max
    end
    level.min = config.min
    level.max = config.max
end

--绘制护石编辑视图
function talisman:draw_edit_view(content)
    if imgui.button("返回") then
        content.editor = nil
        self.talisman  = nil
        return
    end

    imgui.same_line()
    imgui.spacing()
    imgui.same_line()
    if imgui.button("重置") then
        content.editor = nil
        self:normalize_talisman(content)
    end

    imgui.same_line()
    imgui.spacing()
    imgui.same_line()
    if snow.data.DataDef.PlEquipSkillId.none == content.editor.skill[1].id.value then
        imgui.text_colored("第1技能必须有效", 0xFF0000FF)
    elseif imgui.button("确定") then
        self:update_talisman(content)
    end

    imgui.spacing()
    if not imgui.begin_table(nil, 3, imgui.TableFlags.NoSavedSettings | imgui.TableFlags.RowBg) then
        return
    end
    imgui.table_setup_column(nil, imgui.ColumnFlags.WidthFixed)
    imgui.table_setup_column(nil, imgui.ColumnFlags.WidthStretch)
    imgui.table_setup_column(nil, imgui.ColumnFlags.WidthStretch)

    --绘制稀有度编辑控件
    self:draw_rare_editor(content)

    --绘制技能编辑控件
    self:draw_skill_editor(content)

    --绘制插槽编辑控件
    self:draw_slot_editor(content)

    imgui.end_table()
end

--绘制稀有度编辑控件
function talisman:draw_rare_editor(content)
    local editor = content.editor

    imgui.table_next_column()
    imgui.text("稀有")

    imgui.table_next_column()
    imgui.push_id(content.uuid .. "/rare")
    imgui.set_next_item_width(-1)
    local result = select(2, imgui.combo(nil, editor.rare.index, self.ui.rare.text))
    imgui.pop_id()

    if result ~= editor.rare.index then
        editor.rare.index = result
        editor.rare.value = self.ui.rare.value[result]
        self:normalize_talisman(content, editor)
    end

    imgui.table_next_column()
    imgui.text(nil)
end

--绘制技能编辑控件
function talisman:draw_skill_editor(content)
    local editor = content.editor
    local config = {
        skill = self.ui.content[content.editor.rare.value].skill,
        level = self.ui.content[content.editor.rare.value].level,
    }

    for position, skill in pairs(editor.skill) do
        imgui.table_next_column()
        imgui.text("第" .. position .. "技能")

        --绘制技能选择控件
        imgui.table_next_column()
        imgui.push_id(content.uuid .. "/skill-name/" .. position)
        imgui.set_next_item_width(-1)
        local result = select(2, imgui.combo(nil, skill.id.index, config.skill.text[position]))
        imgui.pop_id()

        if result ~= skill.id.index then
            skill.id.index = result
            skill.id.value = config.skill.value[position][result]
            skill.level    = nil
            self:normalize_skill_level(editor, position)

            --排除重复技能
            if editor.skill[1].id.value == editor.skill[2].id.value then
                editor.skill[2].id.index = 1
                editor.skill[2].id.value = snow.data.DataDef.PlEquipSkillId.none
                editor.skill[2].level    = nil
            end

            self:normalize_slot(editor)
        end

        --绘制等级编辑控件
        imgui.table_next_column()
        if not skill.level then
            imgui.text(nil)
            goto next_position
        end

        imgui.push_id(content.uuid .. "/skill-level/" .. position)
        imgui.set_next_item_width(-1)
        result = select(2, imgui.slider_int(nil, skill.level.value, skill.level.min, skill.level.max, "Lv.%d"))
        imgui.pop_id()

        if result ~= skill.level.value then
            skill.level.value = result
        end

        ::next_position::
    end
end

--绘制插槽编辑控件
function talisman:draw_slot_editor(content)
    local editor = content.editor

    imgui.table_next_column()
    imgui.text("插槽")

    if not editor.slot.list then
        imgui.table_next_column()
        imgui.text("0-0-0")
        imgui.table_next_column()
        imgui.text(nil)
        return
    end

    imgui.table_next_column()
    imgui.push_id(content.uuid .. "/slot")
    imgui.set_next_item_width(-1)
    local result = select(2, imgui.combo(nil, editor.slot.index, editor.slot.list.text))
    imgui.pop_id()

    if result ~= content.slot.index then
        editor.slot.index = result
        editor.slot.value = editor.slot.list.value[result]
    end

    imgui.table_next_column()
    imgui.text(nil)
end

--更新给定护石
function talisman:update_talisman(content)
    local editor = content.editor
    content.id = editor.rare.value
    content.slot.value = editor.slot.value
    for position, skill in pairs(editor.skill) do
        content.skill[position].id    = skill.id.value
        content.skill[position].level = skill.level and skill.level.value or 0
    end

    --更新稀有度
    local equipment = snow.data.EquipmentInventoryData(content.instance)
    equipment:set_talisman_id(content.id)

    --更新技能
    local skill_list = equipment:getTalismanSkillIdList()
    local level_list = equipment:getTalismanSkillLvList()
    for skill_index = 1, 2 do
        skill_list[skill_index] = content.skill[skill_index].id
        level_list[skill_index] = content.skill[skill_index].level
    end

    --更新插槽
    local slot_list = equipment:getTalismanDecoSlotNumList()
    for level_index, _ in pairs(slot_list) do
        slot_list[level_index] = 0
    end
    for _, slot in pairs(content.slot.value) do
        if slot ~= 0 then
            slot_list[slot + 1] = slot_list[slot + 1] + 1
        end
    end

    self:load_talisman(content.instance, content)
end

return talisman
